import java.io.BufferedReader;
import java.io.FileReader;
import java.util.ArrayList;

public class ETools20 {

	private static final String source = "data/E.txt";
	private static final Sequence sequence = new Sequence(14);
	private static final Slider slider = new Slider(10);
	private static String message = "";

	public static void main(String[] args) {

		ArrayList<Integer> ackedPackages = new ArrayList<Integer>();
		ArrayList<Packet> sentPackages = new ArrayList<Packet>();
		BufferedReader file;
		try {
			String line;
			file = new BufferedReader(new FileReader(source));
			while ((line = file.readLine()) != null) {
				int lineValue = Integer.parseInt(line);
				// TIMEOUT
				if (lineValue == 15375) {
					System.out.print("=> Timeout : mise en attente ");
					for (int i = 0; i < 15; i++) {
						Thread.sleep(300);
						System.out.print(".");
					}
					System.out.print(" Reprise");
				}

				// MESSAGE TYPE D(x,m)
				if (lineValue >= 0 && lineValue <= 1024) {
					int seqValue = sequence.getCurrent();
					if (seqValue == slider.getEnd()) {
						message += "=> La Sliding Window est pleine.  L'envoi du packet doit attendre.";
					} else {
						int msgValue = (lineValue);
						message += "D(" + seqValue + "," + msgValue
								+ ") : Transmition "
								+ ((seqValue * 1024) + msgValue);
						sentPackages.add(new Packet(seqValue, msgValue));
						sequence.increment();
					}
				}

				// MESSAGE TYPE C(OK,x)
				if (lineValue >= 15360 && lineValue <= 15374) {
					int ackReceived = (lineValue - 15360);
					if (ackedPackages.contains(ackReceived)) {
						for (int i = ackReceived + 1; i < sequence.getCurrent(); i++) {
							message += "D("
									+ i
									+ ","
									+ sentPackages.get(i)
									+ ") : "
									+ ((i * 1024) + sentPackages.get(i)
											.getMessageValue());
						}
					} else {
						System.out.println("Increment");
						ackedPackages.add(ackReceived);
						slider.increment();
					}
				}

				System.out.println(message);
				message = "";
			}
			file.close();
		} catch (Exception e) {
			System.out.println("ERROR : Exception while reading file.");
			e.printStackTrace();
		}
	}
}

class Slider {
	private int size;
	private int start;
	private int end;

	public Slider(int size) {
		this.size = size;
		this.start = 0;
		this.end = this.size;
	}	

	public int getStart() {
		return start;
	}

	public void setStart(int start) {
		this.start = start;
	}

	public int getEnd() {
		return end;
	}

	public void setEnd(int end) {
		this.end = end;
	}

	public void increment() {
		if (this.end == this.size - 1) {
			this.end = 0;
		} else {
			this.end++;
		}
		if (this.start == this.size - 1) {
			this.start = 0;
		} else {
			this.start++;
		}
	}
}

class Sequence {
	private int sequenceSize;
	private int currentElement;

	public Sequence(int size) {
		this.sequenceSize = size;
		this.currentElement = 0;
	}

	public void increment() {
		if (currentElement == sequenceSize) {
			this.currentElement = 0;
		} else {
			this.currentElement++;
		}
	}

	public int getCurrent() {
		return this.currentElement;
	}

	public int getSize() {
		return this.sequenceSize;
	}
}

class Packet {
	private int sequenceValue;
	private int messageValue;
	private PacketTimer timer;

	public Packet(int sequenceValue, int messageValue) {
		this.sequenceValue = sequenceValue;
		this.messageValue = messageValue;
		this.timer = new PacketTimer();
	}

	public int getSequenceValue() {
		return this.sequenceValue;
	}

	public int getMessageValue() {
		return this.messageValue;
	}

	public PacketTimer getTimer() {
		return this.timer;
	}
}

class PacketTimer {
	private static final int MAX_TIME = 5; // en seconde
	private int timeCounter;

	public PacketTimer() {
		this.powerOnTimer();
	}

	public int incrementTimer() {
		if (this.timeCounter < 0)
			return -1;
		if (++this.timeCounter >= MAX_TIME)
			return -2;
		return timeCounter;
	}

	public boolean resetTimer() {
		if (this.timeCounter < 0)
			return false;
		this.timeCounter = 0;
		return true;
	}

	public boolean powerOnTimer() {
		if (this.timeCounter > 0)
			return false;
		timeCounter = 0;
		return true;
	}

	public boolean powerOffTimer() {
		if (this.timeCounter < 0)
			return false;
		this.timeCounter = -1;
		return true;
	}

	public int getTimeCounter() {
		return this.timeCounter;
	}
}